package com.zone.domain.strategy.service.rule.chain;

import com.zone.domain.strategy.model.valobj.RuleActionEnum;
import com.zone.types.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author: zongzi
 * @description: 抽奖过滤器抽象类，实现过滤器通用操作
 * @date: 2024/6/2
 */
@Slf4j
@Service
public abstract class AbstractRaffleRuleFilter implements IRaffleRuleFilter {
    /** 下一个过滤器 */
    private IRaffleRuleFilter nextFilter;

    @Override
    public RaffleRuleFilterChain.StrategyAwardVO doFilter(Long strategyId, String userId, List<String> ruleModels) {
        Validate.notNull(strategyId, "未知的抽奖活动!");
        Validate.notNull(userId, "未知的用户!");
        // 规则模型为空，则不执行过滤器
        RaffleRuleFilterChain.StrategyAwardVO allow = RaffleRuleFilterChain.StrategyAwardVO.allow();
        if (CollectionUtils.isEmpty(ruleModels)) {
            return allow;
        }
        // 当前过滤器不支持该次请求，放行请求
        if (!this.isSupport(ruleModels)) {
            return allow;
        }
        // 调用具体过滤器方法
        log.info("raffle before filter: {}", this.getClass().getSimpleName());
        RaffleRuleFilterChain.StrategyAwardVO ruleActionEntity = this.execute(strategyId, userId);
        log.info("filter execute result: {}", ruleActionEntity);
        if (Objects.equals(ruleActionEntity.getRuleAction(), RuleActionEnum.INTERCEPT)) {
            return ruleActionEntity;
        }
        // 如果当前过滤器无法处理，委派给下一个过滤器
        if (Objects.equals(ruleActionEntity.getRuleAction(), RuleActionEnum.ALLOW) && Objects.nonNull(this.getNextFilter())) {
            return nextFilter.doFilter(strategyId, userId, ruleModels);
        }
        // 所有过滤器无法处理则放行请求
        return allow;
    }

    // 当前拦截器是否可以执行请求
    protected abstract boolean isSupport(List<String> ruleModels);

    // 执行过滤逻辑
    protected abstract RaffleRuleFilterChain.StrategyAwardVO execute(Long strategyId, String userId);

    // 获取下一个过滤器
    public IRaffleRuleFilter getNextFilter() {
        return nextFilter;
    }

    // 设置下一个过滤器
    public void setNextFilter(IRaffleRuleFilter nextFilter) {
        this.nextFilter = nextFilter;
    }
}
